/*
 * hstring.c
 *
 *  Created on: Nov 27, 2011
 *      Author: benoybose
 */

#include "hcstring.h"

#include <string.h>
#include <memory.h>
#include <gc.h>

hcstring* hcstring_create(const char* text) {
    hcstring* string = (hcstring*) GC_MALLOC(sizeof (hcstring));
    if (0 == text) {
        string->text = 0;
        string->length = 0;
    } else {
        int length = strlen(text);
		char* to = 0;
		const char* from = 0;

        length++;
        string->text = (char*) GC_MALLOC(length * sizeof (char));
        memset(string->text, 0, length * sizeof (char));

        to = string->text;
        from = text;
        for (; (*to = *from) != '\0'; ++from, ++to);
        string->length = length - 1;
    }
    return string;
}

hcstring* hcstring_concat(hcstring* string1, hcstring* string2) {
    int length = string1->length + string2->length + 1;
	char* to = 0;
	const char* from  = 0;
	const char* append = 0;

    hcstring* string = (hcstring*) GC_MALLOC(sizeof (hcstring));
    string->text = (char*) GC_MALLOC(length * sizeof (char));
    memset(string->text, 0, length * sizeof (char));

    to = string->text;
    from = string1->text;
    append = string2->text;

    for (; (*to = *from) != '\0'; ++from, ++to);
    while ((*to++ = *append++) != '\0');
    string->length = length;
    return string;
}

hcstring* hcstring_duplicate(hcstring* string) {
    int length = string->length + 1;
	char* to = 0;
	const char* from  = 0;
	int index = 0;

    hcstring* duplicate = (hcstring*) GC_MALLOC(sizeof (hcstring));
    duplicate->text = (char*) GC_MALLOC(length * sizeof (char));
    memset(duplicate->text, 0, length * sizeof (char));

    to = duplicate->text;
    from = string->text;
    index = 0;
    for (; (*to = *from) != '\0'; ++from, ++to, index++);
    duplicate->length = (length - 1);
    return duplicate;
}

int hcstring_compare(hcstring* string1, hcstring* string2) {
    char* s1 = string1->text;
    char* s2 = string2->text;
    while (*s1 == *s2++) {
        if (*s1++ == 0) {
            return (0);
        }
    }
    return (*(unsigned char *) s1 - *(unsigned char *) --s2);
}

int hcstring_index_char(hcstring* string, char ch) {
    char* p = string->text;
    int index = 0;
    for (;; ++p, index++) {
        if (*p == ch) {
            return (index);
        }
        if (!*p) {
            return (-1);
        }
    }
}

int hcstring_last_index_char(hcstring* string, char ch) {
    char* p = string->text;
    int index = 0;
    int position = -1;
    for (;; ++p, index++) {
        if (*p == ch) {
            position = index;
        }
        if (!*p) {
            return position;
        }
    }
    return position;
}

hcstring* hcstring_substr(hcstring* string, int start, int length) {
	char* p = 0;
	char* s = 0;
	char* to = 0;

    int textlength = string->length;
    if ((start < textlength) &&
            (0 <= start)) {
        hcstring* substr = (hcstring*) GC_MALLOC(sizeof (hcstring));
        length++;
        substr->text = (char*) GC_MALLOC(length * sizeof (char));
        memset(substr->text, 0, length * sizeof (char));

        p = string->text + start;
        s = p;
        to = substr->text;
        while ((*p) && ((length - 1) > (p - s))) {
            *to = *p;
            to++;
            p++;
            substr->length++;
        }
        return substr;
    } else {
        return 0;
    }
}

int hcstring_len(hcstring* string) {
    return string->length;
}
